package com.stm.bi.executor;

import com.stm.bi.dto.query.SubjectCategoryTreeQry;
import com.stm.bi.dto.vo.SubjectCategoryTreeVO;
import com.stm.bi.dto.vo.SubjectCategoryVO;
import com.stm.bi.dto.vo.SubjectVO;
import com.stm.bi.repository.report.SubjectCategoryRepository;
import com.stm.bi.repository.report.SubjectRepository;
import com.stm.bi.repository.report.dataobject.SubjectCategoryDO;
import com.stm.framework.core.util.StringUtil;
import com.stm.framework.dto.Response;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;
/**
* 科目分类-查询执行器
*
* @author qinyongjie
* @date 2025-05-22
*/
@Component
public class SubjectCategoryQueryExe{
    @Resource
    private SubjectCategoryRepository subjectCategoryRepository;

    @Resource
    private SubjectRepository subjectRepository;

    //region 主体
    /**
    * 查询一条数据
    * @param id
    */
    public Response<SubjectCategoryVO> selectById(Long id){
        return Response.of(subjectCategoryRepository.selectById(id));
    }

    /**
     * 查询分类树
     */
    public Response<List<SubjectCategoryTreeVO>> selectTree(SubjectCategoryTreeQry qry) {
        if (qry == null) {
            qry = new SubjectCategoryTreeQry();
        }
        
        // 如果传入了科目名称，按科目名称查询逻辑
        if (StringUtil.isNotEmpty(qry.getSubjectName())) {
            return selectTreeBySubjectName(qry.getSubjectName());
        }
        
        // 否则按分类名称查询逻辑（原有逻辑）
        return selectTreeByCategoryName(qry.getCategoryName());
    }
    //endregion


    //region 私有方法区
    
    // 根据分类名称查询分类树（原有逻辑）
    private Response<List<SubjectCategoryTreeVO>> selectTreeByCategoryName(String categoryName) {
        // 查询所有分类（支持按名称模糊搜索）
        List<SubjectCategoryDO> allCategories = subjectCategoryRepository.selectAllCategories(categoryName);
        
        // 构建树形结构
        List<SubjectCategoryTreeVO> tree = buildTree(allCategories);
        
        // 计算科目数量
        calculateSubjectCount(tree, allCategories);
        
        // 对一级分类进行排序：MK->MD->MG
        tree.sort((a, b) -> {
            String labelA = a.getLabel();
            String labelB = b.getLabel();
            
            // 定义排序优先级
            int priorityA = getSortPriority(labelA);
            int priorityB = getSortPriority(labelB);
            
            return Integer.compare(priorityA, priorityB);
        });
        
        return Response.of(tree);
    }
    
    // 根据科目名称查询分类树
    private Response<List<SubjectCategoryTreeVO>> selectTreeBySubjectName(String subjectName) {
        // 1. 根据科目名称模糊查询科目列表
        List<SubjectVO> subjects = subjectRepository.selectBySubjectName(subjectName);
        
        if (CollectionUtils.isEmpty(subjects)) {
            return Response.of(new ArrayList<>());
        }
        
        // 2. 获取所有相关的分类ID
        Set<Long> categoryIds = subjects.stream()
                .map(SubjectVO::getCategoryId)
                .collect(Collectors.toSet());
        
        // 3. 查询相关分类及其父节点路径
        Set<Long> allRelatedCategoryIds = new HashSet<>();
        for (Long categoryId : categoryIds) {
            // 添加当前分类
            allRelatedCategoryIds.add(categoryId);
            
            // 查询当前分类信息，获取其路径，添加所有父节点
            SubjectCategoryDO category = subjectCategoryRepository.getById(categoryId);
            if (category != null && StringUtil.isNotEmpty(category.getPath())) {
                addParentIdsFromPath(category.getPath(), allRelatedCategoryIds);
            }
        }
        
        // 4. 查询所有相关分类
        List<SubjectCategoryDO> allCategories = queryRelatedCategories(allRelatedCategoryIds);
        
        // 5. 构建树形结构
        List<SubjectCategoryTreeVO> tree = buildTree(allCategories);
        
        // 6. 计算科目数量
        calculateSubjectCount(tree, allCategories);
        
        // 7. 对一级分类进行排序：MK->MD->MG
        tree.sort((a, b) -> {
            String labelA = a.getLabel();
            String labelB = b.getLabel();
            
            // 定义排序优先级
            int priorityA = getSortPriority(labelA);
            int priorityB = getSortPriority(labelB);
            
            return Integer.compare(priorityA, priorityB);
        });
        
        return Response.of(tree);
    }
    
    // 从路径中提取父节点ID
    private void addParentIdsFromPath(String path, Set<Long> allRelatedCategoryIds) {
        if (StringUtil.isEmpty(path)) {
            return;
        }
        
        String[] pathIds = path.split(",");
        for (String pathId : pathIds) {
            try {
                Long id = Long.parseLong(pathId.trim());
                if (id > 0) { // 排除根节点0
                    allRelatedCategoryIds.add(id);
                }
            } catch (NumberFormatException e) {
                // 忽略无效的ID
            }
        }
    }
    
    // 查询相关分类
    private List<SubjectCategoryDO> queryRelatedCategories(Set<Long> categoryIds) {
        if (CollectionUtils.isEmpty(categoryIds)) {
            return new ArrayList<>();
        }
        
        return categoryIds.stream()
                .map(subjectCategoryRepository::getById)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    // 构建树形结构
    private List<SubjectCategoryTreeVO> buildTree(List<SubjectCategoryDO> allCategories) {
        // 转换为TreeVO列表
        List<SubjectCategoryTreeVO> allTreeNodes = allCategories.stream()
                .map(this::convertToTreeVO)
                .toList();

        // 按parentId分组
        Map<Long, List<SubjectCategoryTreeVO>> parentMap = allTreeNodes.stream()
                .collect(Collectors.groupingBy(node -> {
                    // 根据当前节点的value找到对应的DO对象，获取其parentId
                    return allCategories.stream()
                            .filter(category -> category.getId().equals(node.getValue()))
                            .findFirst()
                            .map(SubjectCategoryDO::getParentId)
                            .orElse(0L);
                }));

        // 为每个节点设置children
        allTreeNodes.forEach(node -> {
            List<SubjectCategoryTreeVO> children = parentMap.get(node.getValue());
            node.setChildren(children != null ? children : new ArrayList<>());
        });

        // 返回根节点（parentId为0的节点）
        return parentMap.get(0L) != null ? parentMap.get(0L) : new ArrayList<>();
    }

    // 转换为TreeVO
    private SubjectCategoryTreeVO convertToTreeVO(SubjectCategoryDO categoryDO) {
        return new SubjectCategoryTreeVO()
                .setValue(categoryDO.getId())
                .setLabel(categoryDO.getName())
                .setDefinition(categoryDO.getDefinition())
                .setChildren(new ArrayList<>());
    }

    // 计算科目数量
    private void calculateSubjectCount(List<SubjectCategoryTreeVO> tree, List<SubjectCategoryDO> allCategories) {
        // 获取所有分类ID
        List<Long> allCategoryIds = allCategories.stream()
                .map(SubjectCategoryDO::getId)
                .collect(Collectors.toList());
        
        // 查询每个分类的科目数量
        Map<Long, Long> subjectCountMap = subjectRepository.countByCategoryIds(allCategoryIds);
        
        // 递归计算每个节点的科目数量（包括子节点）
        calculateSubjectCountRecursive(tree, subjectCountMap);
    }

    // 递归计算每个节点的科目数量（包括子节点）
    private int calculateSubjectCountRecursive(List<SubjectCategoryTreeVO> nodes, Map<Long, Long> subjectCountMap) {
        int totalCount = 0;
        
        for (SubjectCategoryTreeVO node : nodes) {
            // 当前节点直接的科目数量
            int directCount = subjectCountMap.getOrDefault(node.getValue(), 0L).intValue();
            
            // 子节点的科目数量
            int childrenCount = 0;
            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                childrenCount = calculateSubjectCountRecursive(node.getChildren(), subjectCountMap);
            }
            
            // 当前节点的总科目数量 = 直接科目数量 + 子节点科目数量
            int nodeTotal = directCount + childrenCount;
            node.setSubjectCount(nodeTotal);
            
            totalCount += nodeTotal;
        }
        
        return totalCount;
    }

    // 获取分类标签的排序优先级
    private int getSortPriority(String label) {
        switch (label) {
            case "MK":
                return 1;
            case "MD":
                return 2;
            case "MG":
                return 3;
            default:
                return 999; // 其他分类排在最后
        }
    }
    //endregion

 }
